using MediatR;
using S.O.Api.Write.Application.Command.Medical;
using S.O.Domain.Medical;
using S.O.ErrorCode;
using S.O.Interstructrue;
using S.O.Interstructrue.Base;
using System.Text.RegularExpressions;

namespace S.O.Api.Write.Application.Handler.Medical
{
    /// <summary>
    /// 创建挂号记录处理器
    /// 实现患者挂号的完整业务流程，包括挂号号码生成、费用计算、数据持久化等
    /// </summary>
    public class CreateRegistrationHandler : IRequestHandler<CreateRegistrationCommand, APIResult<string>>
    {
        /// <summary>
        /// 数据库上下文
        /// </summary>
        private readonly RBACDbContext _context;
        
        /// <summary>
        /// 挂号记录仓储
        /// </summary>
        private readonly IBaseRepository<RegistrationModel> _registrationRepository;
        
        /// <summary>
        /// 患者信息仓储
        /// </summary>
        private readonly IBaseRepository<PatientModel> _patientRepository;
        
        /// <summary>
        /// 日志记录器
        /// </summary>
        private readonly ILogger<CreateRegistrationHandler> _logger;

        /// <summary>
        /// 构造函数，通过依赖注入初始化所需服务
        /// </summary>
        /// <param name="context">数据库上下文</param>
        /// <param name="registrationRepository">挂号记录仓储</param>
        /// <param name="patientRepository">患者信息仓储</param>
        /// <param name="logger">日志记录器</param>
        public CreateRegistrationHandler(
            RBACDbContext context,
            IBaseRepository<RegistrationModel> registrationRepository,
            IBaseRepository<PatientModel> patientRepository,
            ILogger<CreateRegistrationHandler> logger)
        {
            _context = context;
            _registrationRepository = registrationRepository;
            _patientRepository = patientRepository;
            _logger = logger;
        }

        /// <summary>
        /// 处理创建挂号记录命令
        /// </summary>
        /// <param name="request">创建挂号记录命令</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>包含挂号单号的API结果</returns>
        public async Task<APIResult<string>> Handle(CreateRegistrationCommand request, CancellationToken cancellationToken)
        {
            try
            {
                // 1. 首先处理患者信息
                var patientId = await CreateOrUpdatePatientInfo(request);
                if (patientId <= 0)
                {
                    return new APIResult<string> { Code = APIEnums.Error, Msg = "患者信息处理失败" };
                }
                
                // 2. 生成挂号单号
                var registrationNo = GenerateRegistrationNo();
                
                // 3. 验证就诊日期不能是过去的日期（允许当天和未来日期）
                if (request.VisitDate.Date < DateTime.Now.Date)
                {
                    return new APIResult<string> { Code = APIEnums.Error, Msg = "就诊日期不能早于当前日期" };
                }
                
                // 4. 验证就诊日期不能超过30天后
                if (request.VisitDate.Date > DateTime.Now.Date.AddDays(30))
                {
                    return new APIResult<string> { Code = APIEnums.Error, Msg = "就诊日期不能超过30天后" };
                }
                
                // 5. 检查同一患者在同一天是否已有挂号记录
                var existingRegistration = _registrationRepository.GetALL()
                    .FirstOrDefault(r => r.PatientId == patientId 
                                        && r.VisitDate.Date == request.VisitDate.Date
                                        && r.Status != "已取消"
                                        && r.IsEnable);
                
                if (existingRegistration != null)
                {
                    return new APIResult<string> { Code = APIEnums.Error, Msg = "该患者在当天已有挂号记录，请选择其他日期或取消原有挂号" };
                }
                
                // 6. 创建挂号记录
                var registration = new RegistrationModel
                {
                    RegistrationNo = registrationNo,
                    PatientId = patientId,
                    CardNo = request.CardNo,
                    PatientName = request.PatientName,
                    RegistrationType = request.RegistrationType,
                    RegistrationFee = request.RegistrationFee,
                    OtherFee = request.OtherFee,
                    Department = request.Department,
                    Doctor = request.Doctor,
                    RegistrationDate = DateTime.Now,
                    VisitDate = request.VisitDate,
                    Status = "待诊",
                    IsEnable = true,
                    CreateTime = DateTime.Now
                };
                
                // 保存到数据库
                _registrationRepository.Create(registration);
                _context.SaveChanges();
                
                return new APIResult<string> { Code = APIEnums.Success, Data = registrationNo, Msg = "挂号成功" };
            }
            catch (Exception ex)
            {
                return new APIResult<string> { Code = APIEnums.Error, Msg = $"挂号失败：{ex.Message}" };
            }
        }
        
        /// <summary>
        /// 生成挂号单号
        /// 格式：GH + 年月日 + 6位序号
        /// </summary>
        /// <returns>挂号单号</returns>
        private string GenerateRegistrationNo()
        {
            var dateStr = DateTime.Now.ToString("yyyyMMdd");
            var randomNum = new Random().Next(100000, 999999);
            return $"GH{dateStr}{randomNum}";
        }
        
        /// <summary>
        /// 创建或更新患者信息
        /// </summary>
        /// <param name="request">挂号请求</param>
        /// <returns>患者ID</returns>
        private async Task<long> CreateOrUpdatePatientInfo(CreateRegistrationCommand request)
        {
            try
            {
                // 验证必填字段
                if (string.IsNullOrWhiteSpace(request.PatientName))
                {
                    _logger.LogError("患者姓名不能为空");
                    return 0;
                }
                
                if (string.IsNullOrWhiteSpace(request.IdCard))
                {
                    _logger.LogError("身份证号不能为空");
                    return 0;
                }
                
                if (string.IsNullOrWhiteSpace(request.Phone))
                {
                    _logger.LogError("联系电话不能为空");
                    return 0;
                }
                
                // 验证身份证号格式
                if (!IsValidIdCard(request.IdCard))
                {
                    _logger.LogError($"身份证号格式不正确: {request.IdCard}");
                    return 0;
                }
                
                // 验证手机号格式
                if (!IsValidPhone(request.Phone))
                {
                    _logger.LogError($"手机号格式不正确: {request.Phone}");
                    return 0;
                }
                
                // 检查身份证号是否已存在
                var existingPatient = _patientRepository.GetALL()
                    .FirstOrDefault(p => p.IdCard == request.IdCard && !p.IsDeleted);
                
                if (existingPatient != null)
                {
                    // 如果患者已存在，更新信息并返回现有ID
                    existingPatient.PatientName = request.PatientName;
                    existingPatient.CardNo = request.CardNo;
                    existingPatient.Gender = request.Gender;
                    existingPatient.Age = CalculateAge(request.BirthDate);
                    existingPatient.BirthDate = request.BirthDate;
                    existingPatient.Phone = request.Phone;
                    existingPatient.Address = request.Address;
                    existingPatient.Ethnicity = request.Ethnicity;
                    existingPatient.Education = request.Education;
                    existingPatient.Occupation = request.Occupation;
                    existingPatient.PostalCode = request.PostalCode;
                    existingPatient.MaritalStatus = request.MaritalStatus;
                    existingPatient.IsEnable = true;
                    
                    _patientRepository.Update(existingPatient);
                    
                    _logger.LogInformation($"更新患者信息成功，患者ID: {existingPatient.Id}, 姓名: {request.PatientName}");
                    return existingPatient.Id;
                }
                
                // 生成医疗卡号（如果未提供）
                if (string.IsNullOrWhiteSpace(request.CardNo))
                {
                    request.CardNo = GenerateCardNo();
                }
                
                // 创建新患者记录
                var patient = new PatientModel
                {
                    PatientName = request.PatientName,
                    CardNo = request.CardNo,
                    IdCard = request.IdCard,
                    Gender = request.Gender,
                    Age = CalculateAge(request.BirthDate),
                    BirthDate = request.BirthDate,
                    Phone = request.Phone,
                    Address = request.Address,
                    Ethnicity = request.Ethnicity,
                    Education = request.Education,
                    Occupation = request.Occupation,
                    PostalCode = request.PostalCode,
                    MaritalStatus = request.MaritalStatus,
                    IsEnable = true,
                    CreateTime = DateTime.Now
                };
                
                // 保存到数据库
                var result = _patientRepository.Create(patient);
                
                if (result > 0)
                {
                    _logger.LogInformation($"创建患者信息成功，患者ID: {patient.Id}, 姓名: {request.PatientName}");
                    return patient.Id;
                }
                else
                {
                    _logger.LogError($"创建患者信息失败，姓名: {request.PatientName}");
                    return 0;
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"创建患者信息时发生异常，姓名: {request.PatientName}");
                return 0;
            }
        }
        
        /// <summary>
        /// 验证身份证号格式
        /// </summary>
        /// <param name="idCard">身份证号</param>
        /// <returns>是否有效</returns>
        private bool IsValidIdCard(string idCard)
        {
            if (string.IsNullOrWhiteSpace(idCard))
                return false;
                
            // 18位身份证号正则表达式
            var pattern = @"^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$";
            return Regex.IsMatch(idCard, pattern);
        }
        
        /// <summary>
        /// 验证手机号格式
        /// </summary>
        /// <param name="phone">手机号</param>
        /// <returns>是否有效</returns>
        private bool IsValidPhone(string phone)
        {
            if (string.IsNullOrWhiteSpace(phone))
                return false;
                
            // 手机号正则表达式
            var pattern = @"^1[3-9]\d{9}$";
            return Regex.IsMatch(phone, pattern);
        }
        
        /// <summary>
        /// 生成医疗卡号
        /// </summary>
        /// <returns>医疗卡号</returns>
        private string GenerateCardNo()
        {
            // 生成格式：年月日 + 4位随机数
            var dateStr = DateTime.Now.ToString("yyyyMMdd");
            var random = new Random().Next(1000, 9999);
            return $"{dateStr}{random}";
        }
        
        /// <summary>
        /// 根据出生日期计算年龄
        /// </summary>
        /// <param name="birthDate">出生日期</param>
        /// <returns>年龄</returns>
        private int CalculateAge(DateTime birthDate)
        {
            var today = DateTime.Today;
            var age = today.Year - birthDate.Year;
            if (birthDate.Date > today.AddYears(-age))
                age--;
            return age;
        }
    }
}